Imports System
Imports System.Collections
Imports System.Runtime.InteropServices
Imports System.IO
Imports System.Text.RegularExpressions
Imports System.Collections.Generic
Imports stigzler
Imports System.Data
Imports System.Windows.Forms
Imports System.Speech.Synthesis
Imports AForge.Controls
Imports AForge
Imports System.Linq

Namespace GameEx

    ''' <summary>
    ''' Internal program info for your plugin.
    ''' </summary>
    Public Structure PluginInfo
        Public Const Name As String = "GEmvoy"
        Public Const Version As String = "1.0.4"
        Public Const Author As String = "Stigzler"
        Public Const Description As String = "Extending Emu and Game setups."
        Public Const PluginType As Plugin_Type = Plugin_Type.Emulator
        Public Const PluginVersion As String = "1.40"
    End Structure

    <StructLayout(LayoutKind.Sequential)> _
    Public Structure GameExInfo
        Public GameExVersion As String
    End Structure
    ''' <summary>
    ''' Declare the type of plugin you'll be using.
    ''' </summary>
    ''' <remarks>Only emulator is implemented at this time.</remarks>
    Public Enum Plugin_Type
        Emulator = 0
        Stand_Alone = 1
    End Enum
    ''' <summary>
    ''' The declaration for your plugin.
    ''' </summary>
    ''' 

    Public Class Plugin

        '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        ' MY GLOBALS
        '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        Public Shared WithEvents GEmvoy As New GEmvoy
        Public Shared GameBio As String = ""

        Public Shared AltEmusForSystem As Boolean = False
        Public Shared SpecifiedEmu As Integer = -1
        Public Shared CurrentEmuKey As Integer = -1
        Public Shared DefEmuForGame As String


        Public Speaker As New SpeechSynthesizer()
        Public SpeechAvailable As Boolean = False

        Public Shared Event Joypad(ByVal JoyCommand As String)

        '  Public Shared BroadcastMode As Boolean = False

        Public PresentPage As Integer = 8

        Public CamHKButts As New List(Of Integer)
        Public EmuHKButts As New List(Of Integer)
        Public CamHKSet As New HashSet(Of Integer)
        Public EmuHKSet As New HashSet(Of Integer)

        Public Shared UsingDInput As Boolean = False


        '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
        ' /GLOBALS
        '++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        Private disposed As Boolean = False
        Public GameExEventQueue As New ArrayList
        ''' <summary>
        ''' The enumeration of your MCE remote's keys (Input_MCERemote Function).
        ''' </summary>
        ''' <remarks>This feature is not yet implemented.</remarks>
        Public Enum MCE_Remote_Key
            MCEButton_OK = 13
            MCEButton_Clear = 27
            MCEButton_MoveLeft = 37
            MCEButton_MoveUp = 38
            MCEButton_MoveRight = 39
            MCEButton_MoveDown = 40
            MCEButton_Number0 = 48
            MCEButton_Number1 = 49
            MCEButton_Number2 = 50
            MCEButton_Number3 = 51
            MCEButton_Number4 = 52
            MCEButton_Number5 = 53
            MCEButton_Number6 = 54
            MCEButton_Number7 = 55
            MCEButton_Number8 = 56
            MCEButton_Number9 = 57
            MCEButton_Number0_2 = 58
        End Enum
        ''' <summary>
        ''' The enumeration of the MCE remote's commands (Input_MCERemote Function).
        ''' </summary>
        ''' <remarks>This feature is not yet implemented.</remarks>
        Public Enum MCE_Remote_Command
            MCEButton_Back = 65536
            MCEButton_Skip = 720896
            MCEButton_Replay = 786432
            MCEButton_Stop = 851968
            MCEButton_Play = 271450112
            MCEButton_Pause = 271515648
            MCEButton_Record = 271581184
            MCEButton_Forward = 271646720
            MCEButton_Rewind = 271712256
            MCEButton_ChannelUp = 271777792
            MCEButton_ChannelDown = 271843328
        End Enum
        ''' <summary>
        ''' The enumeration for your MCE remote's commands (Input_MCERemote Function).
        ''' </summary>
        ''' <remarks>This feature is not yet implemented.</remarks>
        Public Enum MCE_Remote_Raw
            MCEButton_MoreInfo = 9
            MCEButton_DVDMenu = 36
            MCEButton_LiveTV = 37
            MCEButton_MyTV = 70
            MCEButton_MyMusic = 71
            MCEButton_RecordedTV = 72
            MCEButton_MyPictures = 73
            MCEButton_MyVideos = 74
            MCEButton_DVDAngle = 75
            MCEButton_DVDAudio = 76
            MCEButton_DVDSubtitle = 77
            MCEButton_OEM1 = 128
            MCEButton_OEM2 = 129
            MCEButton_Guide = 141
            MCEButton_Mute = 226
            MCEButton_VolumeUp = 233
            MCEButton_VolumeDown = 234
        End Enum
        ''' <summary>
        ''' The enumeration for the favorites mode (Event_Favorites).
        ''' </summary>
        ''' <remarks>This feature is not yet implemented.</remarks>
        Public Enum Favourites_Type
            Add = 0
            Remove = 1
        End Enum
        ''' <summary>
        ''' The enumeration of the App Command codes (App_RunCommand).
        ''' </summary>
        ''' <remarks>
        ''' Currently only Exit, PlayAudioFile, Rotation, Log, and MsgBox are implemented.
        ''' Log will add an entry to the log.txt file, which may be useful for testing.
        ''' </remarks>
        Public Enum App_CMD_Type
            ExitGameEx = 0
            ShutdownPC = 1
            RestartPC = 2
            Minimize = 3
            Restore = 4
            ShowPicture = 5
            ShowWebPage = 6
            PlayAudioFile = 7
            LoadSnapImage = 8
            LoadBackgroundImage = 9
            MsgBox = 10
            Log = 11
            RotateTo0 = 12
            RotateTo90 = 13
            RotateTo270 = 14
        End Enum
        ''' <summary>
        ''' The enumeration of the GameEx Control codes (Event_GameExControl).
        ''' </summary>
        Public Enum GameExControl_Type As Integer
            Up = 0
            Down = 1
            Left = 2
            Right = 3
            SelectEnter = 4
            Back = 5
            Home = 6
            PageUp = 7
            PageDown = 8
            AlphaPageUp = 9
            AlphaPageDown = 10
            VolumeUp = 11
            VolumeDown = 12
        End Enum
        ''' <summary>
        ''' The enumeration for GameEx menus (Event_MenuChange).
        ''' </summary>
        ''' <remarks>This list is currently incomplete/in progress.</remarks>
        Public Enum MenuNumber_Type
            MenuLeft_Item1 = 0
            MenuLeft_Item2 = 1
            MenuLeft_Item3 = 3
            MenuLeft_Item4 = 5
            SelectedGame = 7
            Start = 8
            Jukebox_ByTitle = 10
            Jukebox_ByArtist = 11
            Jukebox_ByAlbum = 12
            Jukebox_ByGenre = 13
            Jukebox_ViewPlayList = 15
            Jukebox_PlayList = 17
            Jukebox_Visualize = 18
            Emulator_Selected = 20
            External_Apps = 30
            Videos = 40
            CPViewer = 50
            LastMameGame = 60
            Mame = 81
            EmulatedGames = 82
            Media = 83
            GamesAndApps = 84
            ExitMenu = 85
            Karaoke = 110
            Pictures = 120
            Radio = 130
            DVD = 410
            News = 500
            YouTube = 503
            ThemePicker = 550
            MostPlayed = 800
            LastPlayed = 801
            Game_ShowNoInfo = 1001
            Game_ShowInfo = 1003
            Search = 2010
        End Enum
        ''' <summary>
        ''' The structure for database entries in GameEx.
        ''' </summary>
        <StructLayout(LayoutKind.Sequential)> _
        Public Structure Database
            Public Category As String
            Public Year As String
            Public Developer As String
            Public Description As String
        End Structure
        ''' <summary>
        ''' The structure for mame info entries in GameEx.
        ''' </summary>
        <StructLayout(LayoutKind.Sequential)> _
        Public Structure Mame_Info
            Public Players As String
            Public Control As String
            Public CloneOf As String
            Public Orientation As String
            Public VideoWidth As Integer
            Public VideoHeight As Integer
            Public Cocktail As Boolean
        End Structure
        ''' <summary>
        ''' The structure for game data entries in GameEx.
        ''' </summary>
        <StructLayout(LayoutKind.Sequential)> _
        Public Structure Game_Info
            Public EmulatorNumber As Integer
            Public EmulatorName As String
            Public GameName As String
            Public ROMPath As String
            Public ROMName As String
            Public GameData As Database
            Public MameInfo As Mame_Info
            Public RomFilter As String
            Public SnapPath As String
            Public TitlePath As String
            Public CmdLine As String
        End Structure
        ''' <summary>
        ''' The default constructor for the plugin.
        ''' </summary>
        ''' 

        Public Sub Plugin()

        End Sub


        ''' <summary>
        ''' The function called to initialize the plugin.
        ''' </summary>
        ''' <returns>Return false if plugin does not initialize and GameEx will disable it.</returns>
        Public Function Initialize(ByVal InfoPtr As IntPtr) As Boolean
            'Gets GameEx's version info.
            Dim Info As GameExInfo = DirectCast(Marshal.PtrToStructure(InfoPtr, GetType(GameExInfo)), GameExInfo)

            '======================================================================
            ' MY CODE
            ' =======================================================================

            If GEmvoy.InitialisePlugin() = False Then
                MsgBox("There are no emulators setup in GameEx - please set some up first before using GEmvoy. Quitting GEmvoy.", MsgBoxStyle.Critical, "No GameEx Emulators setup...")
                Application.Exit()
            End If


            'TEST SPEECH:
            GEmvoy.WriteGVEntry("PLUGIN: Testing speech:")
            Try
                GEmvoy.WriteGVEntry("Success. Number voices: " & Speaker.GetInstalledVoices().Count)
                With Speaker
                    .Rate = 2
                    .Volume = 100
                    .SelectVoiceByHints(VoiceGender.Female, VoiceAge.Teen, 2, System.Globalization.CultureInfo.CurrentCulture)
                End With
                SpeechAvailable = True
            Catch ex As Exception
                GEmvoy.WriteGVEntry("PLUGIN ERROR: problems initialising voice. Run GameEx as administrator to solve. Error msg: " & ex.Message)
                SpeechAvailable = False
            End Try

            If GEmvoy.Setts.CamEnabled = True And
                GEmvoy.Setts.CamUseHotkey = False And
                GEmvoy.Setts.CamWarn = True Then
                App_RunCommand(App_CMD_Type.MsgBox, 0, "Snaps Enabled: " & GEmvoy.Setts.CamMode,
                                           "Disable via GEmvoy Config.")
            End If

            'Setup Cam + Emu Hotkeys
            CamHKButts = SetupButtList(CInt(GEmvoy.Setts.CamGPhotkey))
            CamHKSet = New HashSet(Of Integer)(CamHKButts)

            EmuHKButts = SetupButtList(CInt(GEmvoy.Setts.EmuGPhotkey))
            EmuHKSet = New HashSet(Of Integer)(EmuHKButts)

  

            GEmvoy.WriteGVEntry("PLUGIN: Initialised successfully")

            Return True
        End Function



      
        Public Function SetupButtList(Code As Integer) As List(Of Integer)

            Dim Intlist As New List(Of Integer)
            Dim ButtonsPress As Joystick.Buttons = CType([Enum].Parse(GetType(Joystick.Buttons), Code), Joystick.Buttons)
            Dim picks = [Enum].GetValues(GetType(Joystick.Buttons)).Cast(Of Joystick.Buttons).
                    Where(Function(q) (ButtonsPress And q) = q).
                    ToArray()
            For Each v As Joystick.Buttons In picks
                Intlist.Add(v.ToString().Remove(0, 6))
            Next
            Return Intlist
        End Function


        ''' <summary>
        ''' Displays the form used to configure the plugin via Plugin Manager.
        ''' </summary>
        Public Sub Configure()

            GEmvoy = New GEmvoy()

            Dim config As New Configuration
            ' MsgBox("debug: " & My.Settings.ShowDebug)
            '   GEmvoy.InitialisePlugin(True) ' put true in here to disable separate debug window - FINAL RELEASE
            If GEmvoy.InitialisePlugin(True) = False Then
                MsgBox("There are no emulators setup in GameEx - please set some up first before using GEmvoy. Quitting GEmvoy.", MsgBoxStyle.Critical, "No GameEx Emulators setup...")
                Return
            End If
            'MsgBox("p[ause")
            config.ShowDialog()
            GEmvoy.Dispose()

        End Sub
        ' Return true to tell GameEx process the joystick button
        ' Return false to tell GameEx NOT to process the joystick button


        ''' <summary>
        ''' Called when a joystick button is pressed.
        ''' </summary>
        ''' <param name="Buttons">Joystick buttons.</param>
        ''' <returns>Return true to process the joystick button.</returns>
        Public Function Input_Joystick(ByVal Buttons() As Boolean) As Boolean

            Dim GEButts As New List(Of Integer)

            For i As Integer = 0 To 17
                If Buttons(i) = True Then
                    GEButts.Add(i + 1)
                End If
            Next

            'Check both lists:
            Dim GESet = New HashSet(Of Integer)(GEButts)

            'Check hotkeys:
            If GESet.SetEquals(CamHKSet) Then
                GEmvoy.WriteGVEntry("PLUGIN: Toggle Camsnaps Gamepad Hotkeys pressed. Toggle cam...")
                ToggleCam(GEmvoy.Setts.CamHotkey)
                Threading.Thread.Sleep(300)
                App_RunCommand(App_CMD_Type.RotateTo0, 0, 0, 0)
            ElseIf GESet.SetEquals(EmuHKSet) Then
                GEmvoy.WriteGVEntry("PLUGIN: Emu Cycle Gamepad Hotkeys pressed. Cycle Emu...")
                CycleEmus()
                Threading.Thread.Sleep(300)
            Else
                'GEmvoy.WriteGVEntry("....no hotkey")
            End If



            Return True
        End Function




        ''' <summary>
        ''' This function is called when GameEx processes the MCE Remote's buttons.
        ''' </summary>
        ''' <param name="Key">Enum MCE Remote [Key]</param>
        ''' <param name="Command">Enum MCE Remote [Command]</param>
        ''' <param name="Raw">Enum MCE Remote [Raw]</param>
        ''' <returns>Return true to tell GameEx to process the MCE Remote button.</returns>
        Public Function Input_MCERemote(ByVal Key As Integer, ByVal Command As Integer, ByVal Raw As Integer) As Boolean

            Select Case Key

                Case MCE_Remote_Key.MCEButton_OK

                Case MCE_Remote_Key.MCEButton_Clear

                Case MCE_Remote_Key.MCEButton_MoveLeft

                Case MCE_Remote_Key.MCEButton_MoveUp

                Case MCE_Remote_Key.MCEButton_MoveRight

                Case MCE_Remote_Key.MCEButton_MoveDown

                Case MCE_Remote_Key.MCEButton_Number0

                Case MCE_Remote_Key.MCEButton_Number1

                Case MCE_Remote_Key.MCEButton_Number2

                Case MCE_Remote_Key.MCEButton_Number3

                Case MCE_Remote_Key.MCEButton_Number4

                Case MCE_Remote_Key.MCEButton_Number5

                Case MCE_Remote_Key.MCEButton_Number6

                Case MCE_Remote_Key.MCEButton_Number7

                Case MCE_Remote_Key.MCEButton_Number8

                Case MCE_Remote_Key.MCEButton_Number9

                Case MCE_Remote_Key.MCEButton_Number0_2

            End Select

            Select Case Command

                Case MCE_Remote_Command.MCEButton_Back

                Case MCE_Remote_Command.MCEButton_Skip

                Case MCE_Remote_Command.MCEButton_Replay

                Case MCE_Remote_Command.MCEButton_Stop

                Case MCE_Remote_Command.MCEButton_Play

                Case MCE_Remote_Command.MCEButton_Pause

                Case MCE_Remote_Command.MCEButton_Record

                Case MCE_Remote_Command.MCEButton_Forward

                Case MCE_Remote_Command.MCEButton_Rewind

                Case MCE_Remote_Command.MCEButton_ChannelUp

                Case MCE_Remote_Command.MCEButton_ChannelDown

            End Select

            Select Case Raw

                Case MCE_Remote_Raw.MCEButton_MoreInfo

                Case MCE_Remote_Raw.MCEButton_DVDMenu

                Case MCE_Remote_Raw.MCEButton_LiveTV

                Case MCE_Remote_Raw.MCEButton_MyTV

                Case MCE_Remote_Raw.MCEButton_MyMusic

                Case MCE_Remote_Raw.MCEButton_RecordedTV

                Case MCE_Remote_Raw.MCEButton_MyPictures

                Case MCE_Remote_Raw.MCEButton_MyVideos

                Case MCE_Remote_Raw.MCEButton_DVDAngle

                Case MCE_Remote_Raw.MCEButton_DVDAudio

                Case MCE_Remote_Raw.MCEButton_DVDSubtitle

                Case MCE_Remote_Raw.MCEButton_OEM1

                Case MCE_Remote_Raw.MCEButton_OEM2

                Case MCE_Remote_Raw.MCEButton_Guide

                Case MCE_Remote_Raw.MCEButton_Mute

                Case MCE_Remote_Raw.MCEButton_VolumeUp

                Case MCE_Remote_Raw.MCEButton_VolumeDown

            End Select

            Return True
        End Function
        ''' <summary>
        ''' This event is called when GameEx switches between menus.
        ''' </summary>
        ''' <param name="MenuNumber">Enum MenuNumber</param>
        ''' <returns>Return true to process the menu change event.</returns>
        Public Function Event_MenuChange(ByVal MenuNumber As Integer) As Boolean
            GEmvoy.WriteGVEntry("PLUGIN: Menu Changed: " & MenuNumber & ". " & [Enum].GetName(GetType(MenuNumber_Type), MenuNumber))
            If MenuNumber <> 20 Then
                AltEmusForSystem = False
            End If
            PresentPage = MenuNumber
            ' if menunumber <> game desc rition page then AltEmusForSystem = false
            Return True
        End Function
        ''' <summary>
        ''' This event is called when GameEx processes the navigation controls.
        ''' </summary>
        ''' <param name="Type">Enum GameExControl</param>
        ''' <returns>Return true to tell GameEx to process the keyboard/gamepad button.</returns>
        Public Function Event_GameExControl(ByVal Type As Integer) As Boolean
            Select Case CType(Type, GameExControl_Type)
                Case GameExControl_Type.Up

                    Return True
                Case GameExControl_Type.Down

                    Return True
                Case GameExControl_Type.Left
                    Return True
                Case GameExControl_Type.Right
                    Return True
                Case GameExControl_Type.SelectEnter
                    Return True
                Case GameExControl_Type.Back
                    Return True
                Case GameExControl_Type.Home
                    Return True
                Case GameExControl_Type.PageUp
                    Return True
                Case GameExControl_Type.PageDown
                    Return True
                Case GameExControl_Type.AlphaPageUp
                    Return True
                Case GameExControl_Type.AlphaPageDown
                    Return True
                Case GameExControl_Type.VolumeUp
                    Return True
                Case GameExControl_Type.VolumeDown
                    Return True
            End Select

            Return True
        End Function
        ''' <summary>
        ''' This event is called when a keyboard button is pressed.
        ''' </summary>
        ''' <param name="code">Key Code</param>
        ''' <param name="usingdirectinput">Send true if using Direct Input</param>
        ''' <returns>Return true to tell GameEx process the keyboard button</returns>
        Public Function Input_Keyboard(ByVal code As Integer, ByVal usingdirectinput As Boolean) As Boolean
            ' MsgBox("here")
            If UsingDInput = False Then
                If usingdirectinput Then UsingDInput = True
            End If

            Dim kc As New KeysConverter
            'GEmvoy.WriteGVEntry("PLUGIN: Key Pressed. RawCode, Key (DX) Page: " & kc.ConvertToString(code) & ", " &
            '                    code & " (" & usingdirectinput &
            '                    ") - " & PresentPage)
            If code = GEmvoy.Setts.CamHotkey Then
                'CAM HOTKEY
                ToggleCam(code)
            ElseIf code = GEmvoy.Setts.GEEmuHotkey And PresentPage = 1003 Then
                'EMU HOTKEY
                CycleEmus()
            Else
                'GEmvoy.WriteGVEntry("Not a Function Key..")
            End If
            Return True
        End Function

        Private Sub CycleEmus()
            If AltEmusForSystem = True Then
                ' Specified emu cycle
                GEmvoy.WriteGVEntry("PLUGIN: Emulator Selected: " & CurrentEmuKey & ". " & GEmvoy.SystemEmus(CurrentEmuKey))

                If GEmvoy.SystemEmus.IndexOfKey(CurrentEmuKey) = GEmvoy.SystemEmus.Count - 1 Then
                    CurrentEmuKey = GEmvoy.SystemEmus.Keys(0)
                Else
                    CurrentEmuKey = GEmvoy.SystemEmus.Keys(GEmvoy.SystemEmus.IndexOfKey(CurrentEmuKey) + 1)
                End If
                App_RunCommand(App_CMD_Type.MsgBox, 0, "Boot Using: ", GEmvoy.SystemEmus(CurrentEmuKey))
                If GEmvoy.Setts.SuppSettsAudio = False And SpeechAvailable = True Then
                    Speaker.SpeakAsync("Boot Using: " & GEmvoy.SystemEmus(CurrentEmuKey))
                End If
            Else
                App_RunCommand(App_CMD_Type.MsgBox, 0, "No alternative emulators", "for this System")
            End If
        End Sub

        Private Sub ToggleCam(code As Integer)
            Dim kc As New KeysConverter

            GEmvoy.WriteGVEntry("PLUGIN: CamSnap hotkey pressed. Checking..")
            If GEmvoy.Setts.CamEnabled = True And GEmvoy.Setts.CamUseHotkey = True Then
                GEmvoy.WriteGVEntry("Cam enabled in settings. Toggling state")
                If GEmvoy.GECamEnabled = False Then
                    GEmvoy.TransposeImage()
                    GEmvoy.GECamEnabled = True
                    If GEmvoy.Setts.SuppSettsAudio = False Then
                        My.Computer.Audio.Play(My.Resources.CamSnapsEnabled, AudioPlayMode.WaitToComplete)
                    End If
                    If GEmvoy.Setts.CamMode = "Continuous" Then
                        If GEmvoy.Setts.SuppSettsAudio = False Then
                            My.Computer.Audio.Play(My.Resources.ContinuousMode, AudioPlayMode.Background)
                        End If
                        App_RunCommand(App_CMD_Type.MsgBox, 0, "Snaps Enabled: Continuous Mode",
                                       "[" & kc.ConvertToString(code) & "] to Disable.")
                    ElseIf GEmvoy.Setts.CamMode = "Burst" Then
                        If GEmvoy.Setts.SuppSettsAudio = False Then
                            My.Computer.Audio.Play(My.Resources.BurstMode, AudioPlayMode.Background)
                        End If
                        App_RunCommand(App_CMD_Type.MsgBox, 0, "Snaps Enabled: Burst Mode",
                                       "[" & kc.ConvertToString(code) & "] to Disable.")
                    End If
                Else
                    GEmvoy.GECamEnabled = False
                    If GEmvoy.Setts.SuppSettsAudio = False Then
                        My.Computer.Audio.Play(My.Resources.CamSnapsDisabled, AudioPlayMode.Background)
                    End If
                    App_RunCommand(App_CMD_Type.MsgBox, 0, "Snaps Disabled",
                                       "[" & kc.ConvertToString(code) & "] to Enable.")
                    GEmvoy.RestoreHome()
                End If
            Else
                GEmvoy.WriteGVEntry("Either Cam or Hotkey disabled in settings. Not enabling Cam snaps.")
            End If
        End Sub


        ''' <summary>
        ''' This event is called when an emulator is selected from the UI.
        ''' </summary>
        ''' <param name="EmuName">Returns "MAME", "DAPHNE" or Emulator Title.</param>
        ''' <returns>Return true to tell GameEx process the event</returns>
        Public Function Event_EmulatorLoad(ByVal EmuName As String) As Boolean

            Return True
        End Function
        ''' <summary>
        ''' This event is called when GameEx exits.
        ''' </summary>
        Public Sub Event_App_Exit()
            'MsgBox("quit")
            'SAVE Settings
            GEmvoy.Setts.SaveSetts()
            'Save Database:
            XMLOps.SaveXML(GEmvoy.GemDSM, GEmvoy.XMLFile)


            GEmvoy.Close()
            GEmvoy.Dispose()

        End Sub
        ''' <summary>
        ''' This event is called every second the GameEx UI is accessable.
        ''' </summary>
        Public Sub Event_Timer(ByVal InfoPtr As IntPtr)

            Dim Info As Game_Info = DirectCast(Marshal.PtrToStructure(InfoPtr, GetType(Game_Info)), Game_Info)

        End Sub
        ''' <summary>
        ''' This event is called when the game info is processed from the UI.
        ''' </summary>
        Public Sub Event_GameShowInfo(ByVal InfoPtr As IntPtr)

            Dim Info As Game_Info = DirectCast(Marshal.PtrToStructure(InfoPtr, GetType(Game_Info)), Game_Info)
            ' Info.EmulatorName = GEEmu Title Text

            GEmvoy.WriteGVEntry("====================================")
            GEmvoy.WriteGVEntry("PLUGIN: Game selected in GameEx. GameInfo Vars:")
            GEmvoy.WriteGVEntry("Rom: " & Info.GameName) ' No way to get the extention at this stage!
            GEmvoy.WriteGVEntry("Catagory: " & Info.GameData.Category)
            GEmvoy.WriteGVEntry("Year: " & Info.GameData.Year)
            GEmvoy.WriteGVEntry("Developer: " & Info.GameData.Developer)
            GEmvoy.WriteGVEntry("Path: " & Info.ROMPath)
            GameBio = Info.GameData.Description
            'GEmvoy.WriteGVEntry("Bio: " & GameBio)

            GEmvoy.WriteGVEntry("Figure if is a GEmvoy system and then the emulator options")
            'Figure if is a GEmvoy system and then the emulator options
            If GEmvoy.GetSystemEmus(Info.EmulatorNumber, Info.GameName, Info.ROMPath) Then
                AltEmusForSystem = True
                CurrentEmuKey = -1
            Else
                AltEmusForSystem = False
            End If



            GEmvoy.WriteGVEntry("GEmvoy enabled + alternative Emulators: " & AltEmusForSystem)
            For Each kvp As KeyValuePair(Of Integer, String) In GEmvoy.SystemEmus
                GEmvoy.WriteGVEntry(kvp.Key & ". " & kvp.Value)
            Next



            ' MsgBox(Info.GameData.Description)
        End Sub
        ''' <summary>
        ''' This event is called when a game is selected from the UI.
        ''' </summary>
        Public Sub Event_GameSelect(ByVal InfoPtr As IntPtr)

            Dim Info As Game_Info = DirectCast(Marshal.PtrToStructure(InfoPtr, GetType(Game_Info)), Game_Info)

        End Sub
        ''' <summary>
        ''' This event is called when a game is launched.
        ''' </summary>
        ''' <returns>Return true to tell GameEx process the event.</returns>
        Public Function Event_GameRun(ByVal InfoPtr As IntPtr) As Boolean

            Dim Info As Game_Info = DirectCast(Marshal.PtrToStructure(InfoPtr, GetType(Game_Info)), Game_Info)

            Return True
        End Function
        ''' <summary>
        ''' This event is called when GameEx builds the command line.
        ''' </summary>
        ''' <returns>Returns the command line to be launched.</returns>
        ''' <remarks>
        ''' The CmdLine variable is populated at this time.
        ''' You can return a modified command line here, or simply return nothing to return the same command line.
        ''' </remarks>
        Public Function Event_CommandLine(ByVal InfoPtr As IntPtr) As String

            Dim Info As Game_Info = DirectCast(Marshal.PtrToStructure(InfoPtr, GetType(Game_Info)), Game_Info)

            'Any randomness:
            Try
                If GEmvoy.Setts.RndLaunchPath <> "Disabled" Then
                    GEmvoy.ReplaceSound("launch", GEmvoy.Setts.RndLaunchPath)
                End If
            Catch
                GEmvoy.WriteGVEntry("Error replacing intro sound - check folder path set...", True)
            End Try




            'Set default command line to that as per GameEx:
            Dim CmdLine As String = Info.CmdLine
            GEmvoy.WriteGVEntry("")

            GEmvoy.WriteGVEntry("0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0=0")
            GEmvoy.WriteGVEntry("PLUGIN: Launch Game Triggered. GameInfo Vars:")
            GEmvoy.WriteGVEntry("Catagory: " & Info.GameData.Category)
            GEmvoy.WriteGVEntry("Year: " & Info.GameData.Year)
            GEmvoy.WriteGVEntry("Developer: " & Info.GameData.Developer)
            GEmvoy.WriteGVEntry("Bio: " & GameBio)

            GEmvoy.GameRun(Info)

            'Modify if CmdLine not null from Gemvoy process:
            Dim CmdFromGemvoy As String = GEmvoy.ReturnCmdLine()
            If CmdFromGemvoy <> "" Then
                CmdLine = CmdFromGemvoy
            End If

            GEmvoy.WriteGVEntry("PLUGIN: Final cmd line:" & CmdLine)
            GEmvoy.WriteGVEntry("")


            Return CmdLine
        End Function
        ''' <summary>
        ''' This event is called when GameEx exits a game and returns to the UI.
        ''' </summary>
        Public Sub Event_GameExit(ByVal InfoPtr As IntPtr)

            Dim Info As Game_Info = DirectCast(Marshal.PtrToStructure(InfoPtr, GetType(Game_Info)), Game_Info)
            'Run any "after" support apps now
            GEmvoy.WriteGVEntry("PLUGIN: Game Exit Event...")
            GEmvoy.GameExit()

        End Sub
        ''' <summary>
        ''' This event is called when GameEx updates the MAME game list.
        ''' </summary>
        ''' <param name="MAMEROMPath">The MAME ROM path being used.</param>
        ''' <param name="MAMEPath">The MAME executable path being used.</param>
        ''' <param name="MAMEExe">The MAME executable being used.</param>
        Public Sub Event_MAMEListUpdate(ByVal Type As Integer, ByVal MAMEROMPath As String, ByVal MAMEPath As String, ByVal MAMEExe As String)

            Select Case Type

                Case 0 'Start MAME list update

                Case 1 'End MAME list update

            End Select
        End Sub
        ''' <summary>
        ''' This event is called when GameEx enters and exits Attract Mode.
        ''' </summary>
        ''' <returns>Return true to process the event.</returns>
        Public Function Event_ScreenSaver(ByVal Type As Integer) As Boolean

            Select Case Type

                Case 0 'Enter Attract Mode

                Case 1 'Start Attract Mode

                Case 2 'Exit Attract Mode

            End Select

            Return True
        End Function

        ' Return true to tell GameEx process the event
        ' Return false to tell GameEx NOT to process the event

        ' Not Implemented Yet
        ''' <summary>
        ''' This event is called when a game is added or removed from favorites.
        ''' </summary>
        ''' <param name="Type">Enum Favorites_Type</param>
        ''' <param name="Info">Enum Game_Info</param>
        ''' <returns>Return true to process the event.</returns>
        ''' <remarks>This feature is not yet implemented.</remarks>
        Public Function Event_Favourites(ByVal Type As Favourites_Type, ByVal Info As Game_Info) As Boolean

            Select Case Type

                Case Favourites_Type.Add

                Case Favourites_Type.Remove

            End Select

            Return True
        End Function
        ''' <summary>
        ''' This event runs the commands specified earlier.
        ''' </summary>
        ''' <remarks>Please do not modify this section!</remarks>
        Private Sub App_RunCommand(ByVal Type As App_CMD_Type, ByVal CMD_int As Integer, ByVal CMD_String As String, ByVal CMD_String2 As String)

            GameExEventQueue.Add(System.Convert.ToString(System.Convert.ToInt32(Type)) + "|" + System.Convert.ToString(CMD_int) + "|" + CMD_String + "|" + CMD_String2)

        End Sub
        ''' <summary>
        ''' This event is called every second to get any commands issues by App_RunCommand.
        ''' </summary>
        ''' <remarks>Please do not modify this section!</remarks>
        Public ReadOnly Property App_GetEvent() As String

            Get
                Return _App_GetEvent()
            End Get

        End Property
        ''' <summary>
        ''' This event is called every second to get any commands issues by App_RunCommand.
        ''' </summary>
        ''' <remarks>Please do not modify this section!</remarks>
        Private Function _App_GetEvent() As String

            Dim GXEvent As String = ""

            If (GameExEventQueue.Count > 0) Then

                GXEvent = System.Convert.ToString(GameExEventQueue(0))
                GameExEventQueue.RemoveAt(0)
            End If

            Return GXEvent
        End Function
        ''' <summary>
        ''' This event handles the disposal of unused variables.
        ''' </summary>
        Public Sub Dispose()
            GEmvoy.WriteGVEntry("PLUGIN: GameEx Closing....")
            Dispose(True)
            GC.SuppressFinalize(Me)
        End Sub
        ''' <summary>
        ''' This event handles the disposal of unused variables.
        ''' </summary>
        Private Sub Dispose(ByVal disposing As Boolean)

            If Not (Me.disposed) Then

                If (disposing) Then

                End If
            End If

            disposed = True
        End Sub

#Region " PLUGIN DATA RETURNS "
        Public ReadOnly Property Name() As String
            Get
                Return PluginInfo.Name
            End Get
        End Property

        Public ReadOnly Property Version() As String
            Get
                Return PluginInfo.Version
            End Get
        End Property

        Public ReadOnly Property Author() As String
            Get
                Return PluginInfo.Author

            End Get
        End Property

        Public ReadOnly Property Description() As String
            Get
                Return PluginInfo.Description
            End Get
        End Property

        Public ReadOnly Property PluginType() As Plugin_Type
            Get
                Return PluginInfo.PluginType
            End Get
        End Property

        Public ReadOnly Property PluginVersion() As String
            Get
                Return PluginInfo.PluginVersion
            End Get
        End Property
#End Region

    End Class

End Namespace

